package cn.lg.soar.system.api.manager;

import cn.lg.soar.common.util.current.CurrentThreadContext;
import cn.lg.soar.common.util.current.UserContext;
import cn.lg.soar.common.util.data.DataUtil;
import cn.lg.soar.system.api.model.*;
import cn.lg.soar.system.api.service.IOrgApi;
import cn.lg.soar.system.api.service.IPostApi;
import cn.lg.soar.system.api.service.IRoleApi;
import cn.lg.soar.system.api.service.IUserApi;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;

import java.lang.ref.SoftReference;
import java.util.*;
import java.util.function.Supplier;

/**
 * @author luguoxiang 469599794@qq.com
 * @Date: 2024/1/19 22:38
 * 开源项目：https://gitee.com/lgx1992/lg-soar 求star！请给我star！请帮我点个star！
 */
@Lazy
public class AccountManager {

    @Lazy
    @Autowired
    private IUserApi userApi;
    @Lazy
    @Autowired
    private IRoleApi roleApi;
    @Lazy
    @Autowired
    private IPostApi postApi;
    @Lazy
    @Autowired
    private IOrgApi orgApi;
    @Lazy
    @Autowired
    private AuthenticationManager authenticationManager;

    /**
     * 获取当前用户信息
     * @return
     */
    public AuthUser getUser() {
        Object o = CurrentThreadContext.get("@u");
        if (o == null) {
            Long userId = UserContext.getUserId();
            UserQueryDTO dto = userApi.getById(userId);
            AuthUser authUser = new AuthUser();
            authUser.setId(dto.getId());
            authUser.setUserType(dto.getUserType());
            authUser.setUsername(dto.getUsername());
            authUser.setNickname(dto.getNickname());
            authUser.setAvatar(dto.getAvatar());
            authUser.setCurrentTenantId(dto.getCurrentTenantId());
            o = authUser;
            CurrentThreadContext.put("@u", o);
        }
        return (AuthUser) o;
    }

    /**
     * 获取当前用户角色
     * @return
     */
    public List<AuthRole> getRoleList() {
        return loader("@rs", () -> {
            Long userId = UserContext.getUserId();
            return roleApi.userRoleList(userId);
        });
    }

    /**
     * 获取用户职位
     * @return
     */
    public List<AuthPost> getPostList() {
        return loader("@ps", () -> {
            Long userId = UserContext.getUserId();
            return postApi.userPostList(userId);
        });
    }

    /**
     * 获取用户组织机构
     * @return
     */
    public List<AuthOrg> getOrgList() {
        return loader("@os", () -> {
            Long userId = UserContext.getUserId();
            return orgApi.userOrgList(userId);
        });
    }

    /**
     * 获取绑定的账号
     * @return
     */
    public List<AuthAccountBind> getAccountList() {
        return loader("@ab", () -> {
            Long userId = UserContext.getUserId();
            return userApi.userAccountList(userId);
        });
    }

    /**
     * 是否超级管理员
     * @return
     */
    public boolean isSuperAdministrator() {
        Object o = CurrentThreadContext.get("@sa");
        if (o == null) {
            o = userApi.isSuperAdministrator(UserContext.getUser().getUsername());
            CurrentThreadContext.put("@sa", o);
        }
        return (boolean) o;
    }

    /**
     * 验证用户类型
     * @param userType 用户类型
     * @return
     */
    public boolean hasUserType(Integer userType) {
        return Objects.equals(userType, getUser().getUserType());
    }

    /**
     * 验证用户类型
     * @param userTypes 用户类型
     * @return
     */
    public boolean anyUserType(Collection<Integer> userTypes) {
        if (DataUtil.isEmpty(userTypes)) {
            return false;
        }
        return userTypes.contains(getUser().getUserType());
    }

    /**
     * 验证用户类型
     * @param userTypes 用户类型
     * @return
     */
    public boolean anyUserType(Integer...userTypes) {
        if (DataUtil.isEmpty(userTypes)) {
            return false;
        }
        Integer userType = getUser().getUserType();
        for (Integer x : userTypes) {
            if (Objects.equals(userType, x)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 是否拥有指定角色
     * @param roleCode 角色编码
     * @return
     */
    public boolean hasRoleCode(String roleCode) {
        List<AuthRole> roleList = getRoleList();
        for (AuthRole authRole : roleList) {
            if (Objects.equals(authRole.getCode(), roleCode)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 是否拥有指定角色
     * @param roleCodes 角色编码
     * @return
     */
    public boolean anyRoleCode(Collection<String> roleCodes) {
        if (DataUtil.isEmpty(roleCodes)) {
            return false;
        }
        List<AuthRole> roleList = getRoleList();
        for (AuthRole authRole : roleList) {
            if (roleCodes.contains(authRole.getCode())) {
                return true;
            }
        }
        return false;
    }

    /**
     * 是否拥有指定角色
     * @param roleCodes 角色编码
     * @return
     */
    public boolean anyRoleCode(String...roleCodes) {
        if (DataUtil.isEmpty(roleCodes)) {
            return false;
        }
        Set<String> set = DataUtil.arrayToSet(roleCodes);
        List<AuthRole> roleList = getRoleList();
        for (AuthRole authRole : roleList) {
            if (set.contains(authRole.getCode())) {
                return true;
            }
        }
        return false;
    }

    /**
     * 是否拥有指定角色
     * @param roleId 角色id
     * @return
     */
    public boolean hasRole(Long roleId) {
        return authenticationManager.hasRole(UserContext.getUserId(), roleId);
    }

    /**
     * 是否拥有指定角色
     * @param roleIds 角色id
     * @return
     */
    public boolean anyRole(Collection<Long> roleIds) {
        return authenticationManager.anyRole(UserContext.getUserId(), roleIds);
    }

    /**
     * 是否拥有指定角色
     * @param roleIds 角色id
     * @return
     */
    public boolean anyRole(Long...roleIds) {
        return authenticationManager.anyRole(UserContext.getUserId(), roleIds);
    }

    /**
     * 是否有指定权限
     * @param permit 权限码
     * @return
     */
    public boolean hasPermit(String permit) {
        return authenticationManager.hasPermit(UserContext.getUserId(), permit);
    }

    /**
     * 是否有指定权限
     * @param permits 权限码
     * @return
     */
    public boolean anyPermit(Collection<String> permits) {
        return authenticationManager.anyPermit(UserContext.getUserId(), permits);
    }

    /**
     * 是否有指定权限
     * @param permits 权限码
     * @return
     */
    public boolean anyPermit(String...permits) {
        return authenticationManager.anyPermit(UserContext.getUserId(), permits);
    }

    private <T>T loader(String key, Supplier<T> supplier) {
        Object o = CurrentThreadContext.get(key);
        if (o == null) {
            T value = supplier.get();
            CurrentThreadContext.put(key, new SoftReference<>(value));
            return value;
        }
        o = ((SoftReference<?>) o).get();
        if (o == null) {
            T value = supplier.get();
            CurrentThreadContext.put(key, new SoftReference<>(value));
            return value;
        }
        return (T) o;
    }

}
